/*
 * MCR.h
 *
 *  Created on: Oct 24, 2011
 *      Author: correa
 */

#ifndef MCR_H_
#define MCR_H_

#include "../graph/Graph.h"
#include <pthread.h>
#include <omp.h>
#include "StabSolvers.h"
#include <repository.h>

typedef struct SP {
	int 		q;		// index in the search queue
	int * 		R;		// vertex set
	int* 	cover;	// (weighted) clique cover
	double 		l;  	// (weighted) level in the search tree
	int 		r;		// vertex set size
	int 		p;		// index in the vertex set of the next branch
	int 		f;		// index in the vertex set of the last branch
}subproblem;


class MCR : public SubpGen<subproblem> {
	// repositories
	void* intvecrepo;
	void* doublevecrepo;
	void* subprepo;
	Graph* g;
	subproblem** 	newsubp;//vetor de novos subproblmas
	subproblem* current;
	int* newsubind;
	bool* hasnew;
	int nt;
	int curt;
	double qmax;
protected:
	virtual void pivot(int cand, int r, int * R, int * cover);
	virtual void resort(subproblem*);
	Graph * graph() { return g; };
public:
	MCR(int nt, Graph* gh);

	//MCR(int nt, Graph* g, Weight<double>* w);

	virtual ~MCR();

	subproblem*	root();

	void	generate(subproblem* s, subproblem** queue, int* q, long* nodes);//agora essa função só seta um valor e acorda as threads

	double		getBest();

	int 	numThreads();

};

class MCS : public MCR {
protected:

	void pivot(int cand,int r, int * R, int * cover);

	void resort(subproblem*);
public:

	MCS(int nt, Graph * g) : MCR(nt,g) {};

	//MCS(int nt, Graph * g, Weight<double> * w) : MCR(nt,g, w) {};

	virtual ~MCS() {};
};

class MCRStabSolver : public BackTrack<subproblem> {
public:
	MCRStabSolver(SubpGen<subproblem>* sg):BackTrack<subproblem>(sg){}
    static StabSolver* create(string form, Graph * g);
    static StabSolver* create(string form,int nt, Graph * g);
};

inline StabSolver* MCRStabSolver::create(string form, Graph * g) {
	if (form == "mcr"){
		MCR* mcr = new MCR(1,g);
		MCRStabSolver* m = new MCRStabSolver(mcr);
		return m;
	}else if (form == "mcs"){
		MCS* mcs = new MCS(1,g);
		return new MCRStabSolver(mcs);
	}return NULL;
}

inline StabSolver* MCRStabSolver::create(string form,int nt, Graph * g) {
	if (form == "mcr"){
		MCR* mcr = new MCR(nt,g);
		return new MCRStabSolver(mcr);
	}else if (form == "mcs"){
		MCS* mcs = new MCS(nt,g);
		return new MCRStabSolver(mcs);
	}return NULL;
}

#endif /* MCR_H_ */
